package com.wgh.search.service.impl;

import com.wgh.search.entity.ProductDoc;
import com.wgh.search.entity.SkuDoc;
import com.wgh.search.service.ProductSearchService;
import com.wgh.common.vo.PageResult;
import com.fasterxml.jackson.databind.ObjectMapper;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.FieldSort;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.query_dsl.*;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import co.elastic.clients.elasticsearch.core.bulk.IndexOperation;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.Highlight;
import co.elastic.clients.elasticsearch.core.search.HighlightField;
import co.elastic.clients.elasticsearch.core.search.Suggestion;
import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation;
import co.elastic.clients.elasticsearch.indices.ExistsRequest;
import co.elastic.clients.json.JsonData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 商品搜索服务实现类
 */
@Service
public class ProductSearchServiceImpl implements ProductSearchService {
    
    private static final Logger logger = LoggerFactory.getLogger(ProductSearchServiceImpl.class);
    
    @Autowired
    private ElasticsearchClient esClient;
    
    @Value("${elasticsearch.index.product}")
    private String productIndex;
    
    @Value("${search.page-size}")
    private Integer pageSize;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    @Override
    public PageResult<ProductDoc> searchProducts(String keyword, Long categoryId, Long brandId, 
                                               String priceRange, String sortField, String sortOrder,
                                               Integer pageNum, Integer pageSize, Map<String, Object> filters) {
        // 设置分页参数
        if (pageNum == null || pageNum < 1) pageNum = 1;
        if (pageSize == null || pageSize < 1) pageSize = this.pageSize;
        int from = (pageNum - 1) * pageSize;
        
        try {
            // 构建查询条件
            Query query = buildSearchQuery(keyword, categoryId, brandId, priceRange, filters);
            
            // 创建搜索请求构建器
            SearchRequest.Builder requestBuilder = new SearchRequest.Builder()
                    .index(productIndex)
                    .query(query)
                    .from(from)
                    .size(pageSize);
            
            // 构建排序
            buildSearchSort(requestBuilder, sortField, sortOrder);
            
            // 构建高亮
            buildSearchHighlight(requestBuilder);
            
            // 构建并执行搜索请求
            SearchRequest searchRequest = requestBuilder.build();
            
            // 执行搜索
            SearchResponse<ProductDoc> searchResponse = esClient.search(searchRequest, ProductDoc.class);
            
            // 处理搜索结果
            return processSearchResult(searchResponse, pageNum, pageSize);
        } catch (Exception e) {
            logger.error("搜索商品失败", e);
            return new PageResult<>();
        }
    }
    
    @Override
    public boolean addProductToIndex(ProductDoc productDoc) {
        try {
            // 创建索引请求
            IndexRequest<ProductDoc> request = new IndexRequest.Builder<ProductDoc>()
                    .index(productIndex)
                    .id(productDoc.getId().toString())
                    .document(productDoc)
                    .build();
            
            // 执行请求
            esClient.index(request);
            logger.info("添加商品到索引成功，商品ID: {}", productDoc.getId());
            return true;
        } catch (Exception e) {
            logger.error("添加商品到索引失败，商品ID: {}", productDoc.getId(), e);
            return false;
        }
    }
    
    @Override
    public boolean batchAddProductsToIndex(List<ProductDoc> productDocs) {
        if (productDocs == null || productDocs.isEmpty()) {
            return true;
        }
        
        try {
            // 创建批量操作列表
            List<BulkOperation> bulkOperations = productDocs.stream()
                    .map(productDoc -> new BulkOperation.Builder()
                            .index(new IndexOperation.Builder<ProductDoc>()
                                    .index(productIndex)
                                    .id(productDoc.getId().toString())
                                    .document(productDoc)
                                    .build())
                            .build())
                    .collect(Collectors.toList());
            
            // 创建批量请求
            BulkRequest bulkRequest = new BulkRequest.Builder()
                    .operations(bulkOperations)
                    .build();
            
            // 执行批量请求
            BulkResponse bulkResponse = esClient.bulk(bulkRequest);
            
            if (bulkResponse.errors()) {
                logger.error("批量添加商品到索引失败");
                return false;
            }
            
            logger.info("批量添加商品到索引成功，数量: {}", productDocs.size());
            return true;
        } catch (Exception e) {
            logger.error("批量添加商品到索引异常", e);
            return false;
        }
    }
    
    @Override
    public boolean updateProductInIndex(ProductDoc productDoc) {
        // 更新操作与添加操作相同，Elasticsearch会自动覆盖已有文档
        return addProductToIndex(productDoc);
    }
    
    @Override
    public boolean deleteProductFromIndex(Long productId) {
        try {
            // 创建删除请求
            DeleteRequest request = new DeleteRequest.Builder()
                    .index(productIndex)
                    .id(productId.toString())
                    .build();
            
            // 执行请求
            esClient.delete(request);
            logger.info("从索引中删除商品成功，商品ID: {}", productId);
            return true;
        } catch (Exception e) {
            logger.error("从索引中删除商品失败，商品ID: {}", productId, e);
            return false;
        }
    }
    
    @Override
    public ProductDoc getProductFromIndex(Long productId) {
        try {
            // 创建获取请求
            GetRequest request = new GetRequest.Builder()
                    .index(productIndex)
                    .id(productId.toString())
                    .build();
            
            // 执行请求
            GetResponse<ProductDoc> response = esClient.get(request, ProductDoc.class);
            
            if (response.found()) {
                ProductDoc productDoc = response.source();
                if (productDoc != null) {
                    productDoc.setId(productId);
                    logger.info("从索引中获取商品成功，商品ID: {}", productId);
                    return productDoc;
                }
            }
            logger.warn("索引中不存在商品，商品ID: {}", productId);
            return null;
        } catch (Exception e) {
            logger.error("从索引中获取商品失败，商品ID: {}", productId, e);
            return null;
        }
    }
    
    @Override
    public boolean rebuildProductIndex() {
        // 注意：实际项目中，重建索引通常需要从数据库获取所有商品数据
        // 这里简化实现，只记录日志
        logger.info("开始重建商品索引");
        
        // TODO: 从数据库获取所有商品数据并重新索引
        
        logger.info("商品索引重建完成");
        return true;
    }
    
    @Override
    public List<String> getSearchSuggestions(String keyword, Integer count) {
        if (keyword == null || keyword.isEmpty()) {
            return new ArrayList<>();
        }
        
        try {
            // 创建搜索请求
            SearchRequest searchRequest = new SearchRequest.Builder()
                    .index(productIndex)
                    .suggest(suggest -> suggest
                        .text(keyword)
                        .suggesters("product_suggest", sBuilder -> sBuilder
                            .completion(completionBuilder -> completionBuilder
                                .field("name")
                                .size(count != null ? count : 10)
                            )
                        )
                    )
                    .build();
            
            // 执行搜索请求
            SearchResponse<ProductDoc> searchResponse = esClient.search(searchRequest, ProductDoc.class);
            
            // 解析搜索建议结果
            List<String> suggestions = new ArrayList<>();
            if (searchResponse.suggest() != null) {
                logger.info("获取搜索建议成功，关键词: {}", keyword);
            }
            
            logger.info("获取搜索建议成功，关键词: {}, 建议数量: {}", keyword, suggestions.size());
            return suggestions;
        } catch (Exception e) {
            logger.error("获取搜索建议失败，关键词: {}", keyword, e);
            return new ArrayList<>();
        }
    }
    
    @Override
    public Map<String, Object> getSearchAggregations(String keyword) {
        try {
            // 创建搜索请求构建器
            SearchRequest.Builder requestBuilder = new SearchRequest.Builder().index(productIndex);
            
            // 添加查询条件
            if (keyword != null && !keyword.isEmpty()) {
                requestBuilder.query(query -> query
                        .multiMatch(multiMatch -> multiMatch
                                .query(keyword)
                                .fields("name", "description")
                        )
                );
            }
            
            // 添加分类聚合
            requestBuilder.aggregations("category_agg", aggregation -> aggregation
                    .terms(terms -> terms
                            .field("categoryId")
                            .size(10)
                    )
            );
            
            // 添加品牌聚合
            requestBuilder.aggregations("brand_agg", aggregation -> aggregation
                    .terms(terms -> terms
                            .field("brandId")
                            .size(10)
                    )
            );
            
            // 设置返回结果数量为0，只关心聚合结果
            requestBuilder.size(0);
            
            // 构建并执行搜索请求
            SearchRequest searchRequest = requestBuilder.build();
            SearchResponse<ProductDoc> searchResponse = esClient.search(searchRequest, ProductDoc.class);
            
            // 处理聚合结果
            Map<String, Object> aggregations = new HashMap<>();
            
            // 获取分类聚合结果
            if (searchResponse.aggregations() != null && searchResponse.aggregations().get("category_agg") != null) {
                List<Map<String, Object>> categoryList = new ArrayList<>();
                aggregations.put("categories", categoryList);
            }
            
            // 获取品牌聚合结果
            if (searchResponse.aggregations() != null && searchResponse.aggregations().get("brand_agg") != null) {
                List<Map<String, Object>> brandList = new ArrayList<>();
                aggregations.put("brands", brandList);
            }
            
            return aggregations;
        } catch (Exception e) {
            logger.error("获取搜索聚合失败，关键词: {}", keyword, e);
            return new HashMap<>();
        }
    }
    
    /**
     * 构建搜索查询条件
     */
    private Query buildSearchQuery(String keyword, 
                                Long categoryId, Long brandId, String priceRange, Map<String, Object> filters) {
        // 构建查询
        Query query;
        
        if (keyword != null && !keyword.isEmpty()) {
            query = Query.of(q -> q.multiMatch(m -> m
                    .query(keyword)
                    .fields("name", "description")
            ));
        } else {
            query = Query.of(q -> q.matchAll(m -> m));
        }
        
        // 构建过滤条件
        List<Query> filterQueries = new ArrayList<>();
        
        // 添加分类过滤
        if (categoryId != null) {
            filterQueries.add(Query.of(q -> q.term(t -> t
                    .field("categoryId")
                    .value(categoryId)
            )));
        }
        
        // 添加品牌过滤
        if (brandId != null) {
            filterQueries.add(Query.of(q -> q.term(t -> t
                    .field("brandId")
                    .value(brandId)
            )));
        }
        
        // 添加价格范围过滤
        if (priceRange != null && !priceRange.isEmpty()) {
            String[] prices = priceRange.split("-|", -1);
            if (prices.length == 2) {
                RangeQuery.Builder rangeQueryBuilder = new RangeQuery.Builder().field("price");
                
                if (!prices[0].isEmpty() && !prices[1].isEmpty()) {
                    rangeQueryBuilder.gte(JsonData.of(Double.parseDouble(prices[0])));
                    rangeQueryBuilder.lte(JsonData.of(Double.parseDouble(prices[1])));
                } else if (!prices[0].isEmpty()) {
                    rangeQueryBuilder.gte(JsonData.of(Double.parseDouble(prices[0])));
                } else if (!prices[1].isEmpty()) {
                    rangeQueryBuilder.lte(JsonData.of(Double.parseDouble(prices[1])));
                }
                
                filterQueries.add(Query.of(q -> q.range(rangeQueryBuilder.build())));
            }
        }
        
        // 添加其他过滤条件
        if (filters != null && !filters.isEmpty()) {
            // 实现其他过滤条件的逻辑
        }
        
        // 构建最终查询
        if (!filterQueries.isEmpty()) {
            return Query.of(q -> q.bool(b -> {
                b.must(query);
                filterQueries.forEach(filter -> b.filter(filter));
                return b;
            }));
        } else {
            return query;
        }
    }
    
    /**
     * 构建搜索排序
     */
    private void buildSearchSort(SearchRequest.Builder requestBuilder, String sortField, String sortOrder) {
        // 处理排序参数
        if (sortField != null && !sortField.isEmpty()) {
            boolean isAscending = sortOrder != null && "asc".equalsIgnoreCase(sortOrder);
            
            requestBuilder.sort(sort -> sort
                .field(field -> field
                    .field(sortField)
                    .order(isAscending ? co.elastic.clients.elasticsearch._types.SortOrder.Asc : co.elastic.clients.elasticsearch._types.SortOrder.Desc)
                )
            );
        } else {
            // 添加默认排序：按商品ID降序
            requestBuilder.sort(sort -> sort
                .field(field -> field
                    .field("id")
                    .order(co.elastic.clients.elasticsearch._types.SortOrder.Desc)
                )
            );
        }
    }
    
    /**
     * 构建搜索高亮
     */
    private void buildSearchHighlight(SearchRequest.Builder requestBuilder) {
        requestBuilder.highlight(highlight -> highlight
                .fields("name", field -> field
                        .preTags("<em style='color:red'>")
                        .postTags("</em>")
                )
        );
    }
    
    /**
     * 处理搜索结果
     */
    private PageResult<ProductDoc> processSearchResult(SearchResponse<ProductDoc> searchResponse, Integer pageNum, Integer pageSize) {
        PageResult<ProductDoc> pageResult = new PageResult<>();
        
        // 获取总命中数
        long totalHits = searchResponse.hits().total().value();
        pageResult.setTotal(totalHits);
        
        // 设置当前页码和每页数量
        pageResult.setPageNum(pageNum);
        pageResult.setPageSize(pageSize);
        
        // 处理搜索结果
        List<ProductDoc> productDocs = new ArrayList<>();
        for (Hit<ProductDoc> hit : searchResponse.hits().hits()) {
            try {
                ProductDoc productDoc = hit.source();
                if (productDoc != null) {
                    productDoc.setId(Long.parseLong(hit.id()));
                    
                    // 处理高亮结果
                    if (hit.highlight() != null && hit.highlight().containsKey("name")) {
                        List<String> highlights = hit.highlight().get("name");
                        if (highlights != null && !highlights.isEmpty()) {
                            productDoc.setName(highlights.get(0));
                        }
                    }
                    
                    productDocs.add(productDoc);
                }
            } catch (Exception e) {
                logger.error("转换搜索结果失败，文档ID: {}", hit.id(), e);
            }
        }
        
        pageResult.setList(productDocs);
        
        return pageResult;
    }
}